package com.esd.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.esd.common.pojo.PageResult;
import com.esd.common.pojo.R;
import com.esd.device.entity.Device;
import com.esd.device.entity.Gateway;
import com.esd.device.mapper.DeviceMapper;
import com.esd.device.mapper.GatewayMapper;
import com.esd.device.service.GatewayService;
import com.esd.device.task.DeviceConstants;
import com.esd.device.task.LogJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class GatewayServiceImpl extends ServiceImpl<GatewayMapper , Gateway> implements GatewayService {

    @Autowired
    private DeviceMapper deviceMapper ;

    @Override
    public R deleteGateway(Integer gatewayId) throws SchedulerException {
        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getGatewayId, gatewayId);
        Device device = deviceMapper.selectOne(queryWrapper,false); // false 当出现多条数据时不抛出异常
        if (device != null){
            return R.error("该网关下存在关联的终端！不能删除。");
        }
        Gateway gateway = baseMapper.selectById(gatewayId);
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        JobKey jobKey = new JobKey("job::" + gateway.getServerIp(), "EsdLogGroup");
        scheduler.pauseJob(jobKey);
        scheduler.deleteJob(jobKey);
        baseMapper.deleteById(gatewayId);
        DeviceConstants.GatewayMissTimesMap.remove(gateway.getServerIp());
        return R.ok("删除网关成功！！");
    }

    @Value("${task.repeatSecond}")
    private Integer repeatSecond ;

    @Transactional
    @Override
    public R updateGateway(Gateway gateway) throws SchedulerException {
        Gateway gateway1 = baseMapper.selectById(gateway.getGatewayId());
        LambdaQueryWrapper<Gateway> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Gateway::getServerIp, gateway.getServerIp());
        queryWrapper.or().eq(Gateway::getGatewayName, gateway.getGatewayName());
        List<Gateway> gatewayList = baseMapper.selectList(queryWrapper);
        if (gatewayList.size()>1){
            return R.error("网关IP或者网关名称已存在！不能修改。");
        }
        if (gatewayList.size()==1 && !Objects.equals(gateway.getGatewayId(), gatewayList.get(0).getGatewayId())){
            return R.error("网关IP或者网关名称已存在！不能修改。");
        }
        baseMapper.updateById(gateway);
        // 修改关联的终端的信道
        LambdaQueryWrapper<Device> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Device::getGatewayId, gateway.getGatewayId());
        Device device1 = new Device() ;
        device1.setSignalChannel(gateway.getSignalChannel());
        deviceMapper.update(device1 , queryWrapper1);
        if (!gateway1.getServerIp().equals(gateway.getServerIp())){
            DeviceConstants.LockMap.put(gateway.getServerIp() , new ReentrantLock()) ;
            DeviceConstants.LockMap.remove(gateway1.getServerIp()) ;
            DeviceConstants.GatewayMissTimesMap.remove(gateway1.getServerIp());
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            JobKey jobKey = new JobKey("job::" + gateway1.getServerIp(), "EsdLogGroup");
            scheduler.pauseJob(jobKey);
            scheduler.deleteJob(jobKey);
            JobDetail job = JobBuilder.newJob(LogJob.class)
                    .withIdentity("job::" + gateway.getServerIp(), "EsdLogGroup") // 定义该实例唯一标识
                    .usingJobData("serverIp", gateway.getServerIp())
                    .build();
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger::" + gateway.getServerIp(), "EsdLogGroup") // 定义该实例唯一标识
                    .startNow() // 马上执行
                    //.startAt(triggerStartTime) // 针对某个时刻执行
                    .withSchedule(SimpleScheduleBuilder
                            .repeatSecondlyForever(repeatSecond)) // 每2秒执行一次
                    .build();
            scheduler.scheduleJob(job, trigger);
            scheduler.start();
        }
        return R.ok("网关信息修改成功！！") ;
    }

    @Override
    public R findPage(Map<String, Object> params) {
        LambdaQueryWrapper<Gateway> queryWrapper = new LambdaQueryWrapper<> ();
        String queryString = (String) params.get("queryString");
        if (queryString != null && !queryString.trim().equals("")){
            queryWrapper.eq(Gateway::getServerIp, queryString);
        }
        Page<Gateway> page = new Page<>((Integer) params.get("currentPage") , (Integer) params.get("pageSize")) ;
        baseMapper.selectPage(page ,queryWrapper) ;
        return R.ok(new PageResult(page.getTotal(),page.getRecords()));
    }

    @Override
    public R addGateway(Gateway gateway) throws SchedulerException {
        LambdaQueryWrapper<Gateway> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Gateway::getServerIp, gateway.getServerIp());
        queryWrapper.or().eq(Gateway::getGatewayName, gateway.getGatewayName());
        Gateway gateway1 = baseMapper.selectOne(queryWrapper,false);
        if (gateway1 != null){
            return R.error("网关IP或者网关名称已存在！不能新增!!");
        }
        baseMapper.insert(gateway);
        DeviceConstants.LockMap.put(gateway.getServerIp() , new ReentrantLock()) ;
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        JobDetail job = JobBuilder.newJob(LogJob.class)
                .withIdentity("job::" + gateway.getServerIp(), "EsdLogGroup") // 定义该实例唯一标识
                .usingJobData("serverIp", gateway.getServerIp())
                .build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger::" + gateway.getServerIp(), "EsdLogGroup") // 定义该实例唯一标识
                .startNow() // 马上执行
                //.startAt(triggerStartTime) // 针对某个时刻执行
                .withSchedule(SimpleScheduleBuilder
                        .repeatSecondlyForever(repeatSecond)) // 每2秒执行一次
                .build();
        scheduler.scheduleJob(job, trigger);
        scheduler.start();

        return R.ok("新增网关成功!!");
    }

    @Autowired
    private GatewayMapper gatewayMapper ;


    @Override
    public R checkGatewayConnection(String lineName) {
        List<String> serverIps ;
        if (lineName.equals("allLine")){
            serverIps =  gatewayMapper.getAllUsingGateway() ;
        }else {
            serverIps =  gatewayMapper.getLineGateways(lineName) ;
        }
        List<Map<String , Object>> result = new ArrayList<>();
        serverIps.forEach(serverIp -> {
            Map<String , Object> map = new HashMap<>() ;
            if (DeviceConstants.GatewayMissTimesMap.containsKey(serverIp)){
                Integer timeoutTime =  DeviceConstants.GatewayMissTimesMap.get(serverIp);
                if (timeoutTime != null && timeoutTime == 10 ){
                    map.put("connected", false) ;
                }else{
                    map.put("connected", true) ;
                }
            }else {
                map.put("connected", true) ;
            }
            map.put("serverIp", serverIp) ;
            result.add(map) ;
        });
        return R.ok(result);
    }
}
